﻿using System;
using System.Collections.Generic;
using System.Linq;
using Nuwanda.TfsSpotlight.Shell.Proxies;
using Nuwanda.TfsSpotlight.Shell.Proxies.Interfaces;
using Nuwanda.TfsSpotlight.Shell.Services.Interfaces;
using StructureMap;

namespace Nuwanda.TfsSpotlight.Shell.Services
{
    /// <summary>This service gives acces to tabs</summary>
    [Pluggable("TabsService")]
    public class TabsService : ITabsService
    {
        private ITabPresenter _activeTabPresenter;

        private ITabStrip TabStrip { get; set; }
        private IAsyncService AsyncService { get; set; }

        public List<ITabPresenter> Tabs { get; private set; }

        public TabsService(ITabStrip tabStrip, IAsyncService asyncService)
        {
            this.TabStrip = tabStrip;
            this.Tabs = new List<ITabPresenter>();
            this.AsyncService = asyncService;
        }

        private bool ContainsTab(ITabPresenter presenter)
        {
            return this.Tabs.Exists(tabPresenter => tabPresenter.IsEqualTo(presenter));
        }

        private ITabStripItem FindTab(ITabPresenter presenter)
        {
            var presenterFound = this.Tabs.Find(tabPresenter => tabPresenter.IsEqualTo(presenter));

            if (presenterFound != null)
                return presenterFound.Tab;

            return null;
        }

        private void ActivateTab(ITabPresenter presenter)
        {
            if (!this.ContainsTab(presenter)) return;

            var tab = this.FindTab(presenter);
            this.TabStrip.SelectTab(tab);
        }

        /// <summary>Handles tab removal</summary>
        public void HandleTabRemoved(ITabPresenter presenter)
        {
            if (!this.ContainsTab(presenter)) return;

            presenter.HandleDeactivation();
            presenter.HandleClose();
            this.Tabs.Remove(presenter);
        }

        /// <summary>Handles tab selection</summary>
        public void HandleSelectedTabHanged(ITabPresenter presenter)
        {
            if (this._activeTabPresenter!= null)
            {
                this._activeTabPresenter.HandleDeactivation();
            }

            presenter.HandleActivation();

            this._activeTabPresenter = presenter;
        }

        /// <summary>A number of opened tabs</summary>
        public int TabsCount
        {
            get { return this.Tabs.Count; }
        }

        /// <summary>Checks whetcher thare are tabs working</summary>
        public bool IsAnyOfTabsWorking
        {
            get
            {
                var isWorking = false;
                foreach (var presenter in this.Tabs)
                {
                    isWorking |= presenter.IsWorking;
                }

                return isWorking;
            }
        }

        /// <summary>
        /// Adds a given tab to tab strip or activates the tab
        /// if there is one already
        /// </summary>
        public void OpenTab(ITabPresenter presenter)
        {
            if (presenter == null) return;

            if (this.ContainsTab(presenter))
            {
                this.ActivateTab(presenter);
            }
            else
            {
                ITabStripItem tab = new TabStripItem
                                        {
                                            View = presenter.Control, 
                                            Presenter = presenter
                                        };

                presenter.Tab = tab;

                this.Tabs.Add(presenter);
                this.TabStrip.AddTabAndActivate(tab);
                this.AsyncService.QueueInPool(presenter.HandleLoad);
            }
        }

        /// <summary>Closes a given tab</summary>
        public void CloseTab(ITabPresenter presenter)
        {
            if (!this.ContainsTab(presenter)) return;

            presenter.WaitTillTheEndOfTheWork();
            var tab = this.FindTab(presenter);
            this.TabStrip.RemoveTab(tab);
            this.HandleTabRemoved(presenter);
        }

        /// <summary>Retrieves currently active tab</summary>
        public T GetActiveTab<T>()
        {
            if (this._activeTabPresenter == null) return default(T);
            if (!typeof(T).IsAssignableFrom(this._activeTabPresenter.GetType())) return default(T);

            return (T)this._activeTabPresenter;
        }

        /// <summary>Closes all tabs</summary>
        public void CloseAllTabs()
        {
            foreach (var presenter in new List<ITabPresenter>(this.Tabs))
            {
                this.HandleTabRemoved(presenter);
                this.TabStrip.RemoveTab(presenter.Tab);
            }
        }

        public List<ITabPresenter> GetTabs(Func<ITabPresenter, bool> filter)
        {
            return (from tabPresenter in this.Tabs
                    where filter(tabPresenter)
                    select tabPresenter).ToList();
        }
    }
}